題目除了基本 Notification Card 介面樣式以外,還有兩個重要的介面
Menu
Search
上面的圖是題目,而我們要做出幾乎一樣的樣子,題目中還有附上出題官方的CodePen,也有附上給我們解題用的template,當我們真的不會的時候,還是可以參考他們的寫法,所以沒有想像中困難。
我做好的此題CSS Challeage解答
那麼我們就開始吧。
這個題目要求我們製作一個通知介面
這裡我覺得挑戰的是
<div class="frame">
<!-- card -->
<div class="card">
<header>
<div class="menuIcon"></div>
<h1>Notifications</h1>
<button class="searchIcon">
<i class="fa fa-search search-icon"></i>
</button>
</header>
<div class="content"></div>
</div>
<!-- menu -->
<div class="menuList"></div>
</div>
由於這次題目算起來有三個介面,所以照慣例,我們先開出基本的版型,複雜的內容都先不要管他。
在這裡我們就先分兩塊 .card
跟 .menuList
,.menuList
開出來之後,就先去CSS內先把他 display:none
,我們之後再來管他,先專注在主要的通知卡片。
.card
內我們照慣例分上下,上半截我直接用 header
,下面我就取名為 .content
。
這邊的 .searchIcon
一樣是使用 css challenge 官方的 font-awesome 來製作,當然你也可以用自己的。
那這邊因為我們需要用到一些有自帶 padding
margin
line-height
等等的物件,所以要記得在最前面把他做 css reset 唷。
// reset
h1, p, button, input, header, i, span, ul, li {
padding: 0;
margin: 0;
line-height: 1;
border: none;
}
.frame {
...
background: #264057;
}
先用我們第一天教的小工具來吸最外面深藍色的底色。
$cardWH: 300px;
...
.card {
...
background-color: #fff;
box-shadow: 10px 10px 15px 0 rgba(0,0,0,0.3);
color: #666;
width: $cardWH;
height: $cardWH;
z-index: 2;
border-radius: 3px;
overflow: hidden;
}
再來就是把template內的 .center
改名成 .card
,用第一天教的小工具尺來算出寬高,把寬高定好。
由於我們等等底下會放一層Menu,所以這邊先設定 z-index: 2
,並且依照題目的樣式作了一點點的圓角,並且設定 overflow: hidden
以確保東西超出去之後會被隱藏。
$blue: #5F98CD;
$headerH: 60px;
...
header {
background-color: $blue;
width: 100%;
height: $headerH;
padding: 14px 20px;
box-sizing: border-box;
position: relative;
}
這裡就一樣使用剛剛吸色的小工具來把上面淺藍色給吸起來。
寬度我希望他能夠順應外面的卡片寬,所以我用 width: 100%
。
接著設定卡片內上下左右的 padding
好讓裡面的東西不會黏在邊緣,因為要設定 padding
,這邊記得加上 box-sizing: border-box
才能讓寬度不會變成 100% + padding
。
然後我們希望這裡會是一個畫布,他上面的東西都要以他的寬高為基準來移動,所以加上這行 position: relative
。
$contentH: $cardWH - $headerH;
...
.content {
position :relative;
width: $cardWH;
height: $contentH;
overflow: hidden;
}
這邊就是基本的設定它的寬高,然後我們就可以開始做裡面。
現在全部弄好了的話長這樣:
...
header {
...
display: flex;
justify-content: space-between;
align-items: center;
}
因為我們要讓裡面的 menuIcon
、H1
、.searchIcon
左右並排在同一排,所以加上 display: flex
並使用 align-items: center
讓他們在同一個水平線高度。
接著使用 justify-content: space-between
這個屬性,讓裡面的物件左右貼到容器的最邊緣,並平均分配間距。
像圖片我們可以看到,虛線外圍那一圈綠色,就是我們一開始給 header
的 padding
。
最左邊 menuIcon
裡面因為目前沒有放東西,所以看起來沒有東西,但他仍然有被算在顯示的物件內。
menuIcon
右邊先有了一個紫色間距,然後才是 H1
。
H1
右邊又是一個一樣寬度的紫色間距,然後才是 .searchIcon
。
H1
Titleheader {
...
h1 {
color: #fff;
font-size: 16px;
font-weight: 600;
text-align: center;
}
}
確定前面有做好 css reset 的話,這邊我們只需要簡單的把樣式設定好就可以。
.searchIcon
$headerIconWH: 30px;
...
header{
...
.searchIcon {
border: none;
background-color: transparent;
width: $headerIconWH;
height: $headerIconWH;
color: #fff;
cursor: pointer;
font-size: 21px;
opacity: 0.5;
font-weight: bold;
text-align: right;
transition: all ease-in .2s;
&:hover {
opacity: 1;
}
}
}
由於 button
本身會自帶邊框跟背景色,所以在這邊先把它們移除。
接著設定一個寬高,我用變數,因為等等左邊的 menuIcon
應該也會用到,所以設定一個高度讓兩邊一致。
接著把它的視覺樣式調整一下,設定好大小,粗細等等。
不要忘記加上滑鼠指上的效果,設定 cursor: pointer
。
然後是視覺樣式上,一開始預設的透明度是 opacity: 0.5
,等滑鼠指上後要變成 opacity: 1
,為了讓這個動態是漸變的,我們加上 transition: all ease-in .2s
。
.menuIcon
我個人覺得這顆 MenuIcon 有點討厭...
依照題目,他分成上下兩條線條,邊緣都有圓角,兩條線條之間的 gap 很寬。
上面那條線條的右邊是一顆稍大的圓點,他跟線條之間的 gap 很小。
這顆按鈕內的元素,除了高度不一樣(線條與圓點),它們之間的 gap 也不太一樣,個人覺得處理起來有點煩,我又不想要用 absolute
的方式來畫(好啦,可能是我自己的問題,我就是覺得用 absolute
來畫太無聊),所以我用其他方式畫了看看。
<div class="card">
<header>
<div class="menuIcon">
<div class="menuLineTop"></div>
<div class="menuDot"></div>
<div class="menuLineBottom"></div>
</div>
</header>
</div>
首先,拉出這顆 icon 的基本版型:.menuLineTop
:這是左上角那條線條。.menuDot
:這是右上角的圓點。.menuLineBottom
:這是下面那條線條。
都取好名字之後,我們就開始做樣式。
header {
...
.menuIcon {
width: $headerIconWH;
height: $headerIconWH;
display: grid;
gap:0 ;
opacity: 0.6;
box-sizing: border-box;
padding: 4px 0;
cursor: pointer;
transition: all ease-in .2s;
z-index: 2;
grid-template-columns: 1fr 7px;
grid-template-rows: 1fr 1fr;
&:hover {
opacity: 1;
}
}
}
首先,設定 .menuIcon
的寬高,這邊就用跟剛剛 .searchIcon
一樣的寬高就可以了。
然後再這邊設定他的 opacity
數值跟滑鼠樣式,因為等等是滑鼠指上這一整個區塊,都要觸發透明度的變化,所以要寫在這裡。最後不忘加上 transition
。
然後我們把他設定成 display: grid
之後,開始設定這兩條的樣式:
grid-template-columns: 1fr 7px
:這一句是設定 column
的樣式。
column
會自動延展填滿可用空間。column
則固定 7px
寬。grid-template-rows: 1fr 1fr
:這一句是設定 row
的樣式。
row
自動延展至剩餘的空間。接著來寫線條的樣式:
header {
...
.menuIcon {
...
[class^="menuLine"] {
background-color: #fff;
height: 3px; [class^="menuLine"] {
background-color: #fff;
height: 3px;
border-radius: 6px;
align-self: center;
}
}
}
這邊先使用選擇器,選擇名字前面是 menuLine
的物件 [class^="menuLine"]
,去設定它們的樣式。
基本的顏色跟高度還有圓角,然後不要忘記把它們上下置中。
header {
...
.menuIcon {
...
[class^="menuLine"] {
...
}
.menuLine {
&Top {
grid-column: 1 / span 1;
}
&Bottom {
grid-column: 1 / span 2;
}
}
}
}
接著就去設定它們各自佔的比例。
我們剛剛前面已經設定過了 grid-template-columns: 1fr 7px
,所以可以知道我們每行 row
是有 2 個 column
的。
而這邊的 menuLineTop
:grid-column: 1 / span 1
這是指他佔有的 column
是從該行 ( row
) 的第一格 column
開始算,佔據 1 格。
而 menuLineBottom
:grid-column: 1 / span 2
這是指他佔有的 column
是從該行 (也就是第二個 row
) 的第一格 column
開始算,佔據 2 格。
header {
...
.menuIcon {
...
.menuDot {
width: 7px;
height: 7px;
border-radius: 5px;
background-color: #fff;
align-self: center;
justify-self: end;
}
}
}
然後就是 icon 右上角的小點點 .menuDot
了,這邊設定好我們原先預計的寬高之後,加上圓角,剛做好的時候會長這樣。
看的出來這整個 grid
是有依照我們本來的預測在跑的。
第一行的右側圓點 7px
,左側線條跟第二行的線條,都跟我們預期的一樣,是自動延展填滿整個空間。看起來沒有任何問題,除了第一行的兩個 column
之間應該要有點小空隙以外。
...
.menuLine {
&Top {
grid-column: 1 / span 1;
margin-right: 3px;
}
這時候我們就回到剛剛第一行左邊的線條那邊,加上一行 margin-right: 3px
讓他往右邊多一點空隙,這樣就完成囉~
由於篇幅太長了,我決定分兩篇寫,下一篇再來寫後面的 Notification Card 的 .content
、Menu、Search。
希望改變了這種按照步驟的寫法,能讓更多人看得懂,也能跟我一樣喜歡上寫CSS。
那今天就先到這裡,明天我們再繼續來玩下一集。